import java.util.*;
/*
*                    ArrayList
*          List      LinkedList
*                    Vector(市场淘汰)
*                    Stack和queue(不常提起这两个)
*/

public class list {
    public static void main(String[] args) {

        /*List接口的特有方法：
          1.add(int index, E element) 在指定位置添加元素
          2.remove(int index) 删除指定位置的元素
          3.get(int index) 获取指定位置的元素
          4.set(int index, E element) 修改指定位置的元素
          5.indexOf(Object o) 返回指定元素的索引
          6.lastIndexOf(Object o) 返回指定元素的最后一次出现的索引
         */
        System.out.println("\n\n-------------------------------------------------");
        System.out.println("List接口的特有方法：");
        List<String> list = new ArrayList<>();
        //1.添加元素
        list.add("aaa");
        list.add(1, "bbb");//索引不能越界，否则会抛出IndexOutOfBoundsException异常
        list.add("ccc");
        System.out.println(list);//[aaa, bbb, ccc]
        //2.删除元素
        //collection接口的remove()方法是删除指定元素，而List接口的remove()方法是删除指定索引的元素
        //当数据里类型是Integer且有元素1，发生方法重载，优先调用实参跟形参类型匹配的方法
        list.remove(1);
        System.out.println(list);//[aaa, ccc]
        //3.获取元素
        System.out.println(list.get(1));//ccc
        //4.修改元素
        list.set(1, "ddd");
        System.out.println(list);//[aaa, ddd]
        //5.返回指定元素的索引
        System.out.println(list.indexOf("aaa"));//0
        //6.返回指定元素的最后一次出现的索引
        list.add("aaa");
        System.out.println(list.lastIndexOf("aaa"));//2

        /*List接口的遍历方式：
        1.迭代器遍历
        2.列表迭代器遍历(迭代器的子接口，ListIterator)
        3.增强for循环遍历
        4.lambda表达式遍历
        5.普通for循环遍历(因为List接口有索引，所以可以用普通for循环遍历)
         */
        System.out.println("\nList接口的遍历方式：");
        System.out.println("列表迭代器遍历：");
        ListIterator<String> it1 = list.listIterator();//获取迭代器，指向集合0索引处
        while (it1.hasNext()) {
            String s = it1.next();
            //与collection接口的迭代器不同，List接口的迭代器可以用set()方法修改添加add()方法添加的元素
            if (s.equals("aaa")) it1.set("ccc");
            if (s.equals("ddd")) it1.add("jjj");
            System.out.print(s + " ");//ccc ddd jjj ccc
        }
        System.out.println("\n增强for循环遍历：");
        for (var s : list) System.out.print(s + " ");//ccc ddd jjj ccc
        System.out.println("\nlambda表达式遍历：");
        list.forEach(s -> System.out.print(s + " "));//accc ddd jjj ccc
        System.out.println("\n普通for循环遍历：");
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i) + " ");//ccc ddd jjj ccc
        }

        /*五种遍历方式的区别：
         * 迭代器遍历   在遍历中需要删除元素
         * 列表迭代器遍历   在遍历中需要添加元素
         * 增强for循环and Lambda表达式遍历   只是遍历
         * 普通for循环遍历   遍历时候想操作索引
         * */


        //ArrayList自己没有什么特别的方法，只是实现了List接口的方法，所以ArrayList的方法都是List接口的方法
        //不多介绍方法怎么用了主要看一下底层原理
        //java中的gather(集合)就是c++中的STL
        //java只有静态/动态初始化数组，那么这次我们学C++中vector一样的动态数组
        ArrayList<Integer> a = new ArrayList<>();//Integer表示元素是int类型,String表示元素是String类型
        //容器都经过java自动处理，输出的不是地址，而是值，跟c++一样
        System.out.println(a);//什么都没有，集合默认是“[]”
        System.out.println("ArrayList集合底层原理介绍(在本输出下这个注释里)：");
        /*  ArrayList集合底层原理
           1.利用空参创建的集合，在底层创建一个默认长度为0的数组
           2.添加第一个元素时，底层会创建一个新的长度为10的数组存满时，会扩容1.5倍
           3.如果一次添加多个元素，1.5倍还放不下，则新创建数组的长度以实际为准
        * */


        //LinkedList(就是双向链表了)
        System.out.println("\n-------------------------------------------------");
        System.out.println("LinkedList特有方法：");
        /*1.addFirst(E e) 在链表的开头添加元素
         * 2.addLast(E e) 在链表的结尾添加元素
         * 3.getFirst() 获取链表的第一个元素
         * 4.getLast() 获取链表的最后一个元素
         * 5.removeFirst() 删除链表的第一个元素
         * 6.removeLast() 删除链表的最后一个元素
         * */
        LinkedList<String> l = new LinkedList<>();
        //添加元素
        l.addFirst("aaa");
        l.addLast("bbb");
        l.addFirst("ccc");
        l.addLast("ddd");
        System.out.println(l);//[ccc, aaa, bbb, ddd]
        //获取元素
        System.out.println(l.getFirst());//ccc
        System.out.println(l.getLast());//ddd
        //删除元素
        l.removeFirst();
        l.removeLast();
        System.out.println(l);//[aaa, bbb]

    }
}
